﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// SDD# - Software Defined Devices in C# for Linux and Windows
// Manager for loadable Apps
// (c) 2014-2015 Chris Burri. MIT License applies. 
// See http://niston.wordpress.com


namespace sdd.apps
{
    public class ApplicationManager
    {
        private List<IApplication> _Apps;
        private sdd.subsystems.ui.MenuItem mnuAppsList;
        public Director Director { internal set; get; }
        public IApplication CurrentApp { private set; get; }

       

        public ApplicationManager(Director directorReference)
        {
            _Apps = new List<IApplication>();
            Director = directorReference;
            mnuAppsList = new subsystems.ui.MenuItem("sdd.menu.appManager.apps_list", "Applications");
            Director.ScreenManager.Menus.Register(mnuAppsList, Director.SystemMenu);
        }

        ~ApplicationManager()
        {
            UnloadAll();
            _Apps = null;
        }

        public IApplication Application(string appName)
        {
            foreach (IApplication app in _Apps)
            {
                if (app.Name == appName) { return app; }
            }
            return null;
        }

        public void Load(string assemblyName, string typeName)
        {
            // create assembly path for app to load
            char dirSep = System.IO.Path.DirectorySeparatorChar;
            string asmNamespace = "sdd.apps";
            string assemblyPath = Environment.CurrentDirectory + dirSep + assemblyName + ".dll";

            // load assembly into current appdomain
            AppDomain.CurrentDomain.Load(System.IO.File.ReadAllBytes(assemblyPath));

            try
            {
                // create an instance of IApplication implementation from the loaded assembly
                IApplication newApp = (IApplication)(Activator.CreateInstance(assemblyName, asmNamespace + "." + typeName).Unwrap());

                // success, add it to list of added applications
                _Apps.Add(newApp);

                // hand it a reference to the Director object
                newApp.Director = Director;

                // run initialization event on the App
                newApp.Initialize();

                // register the App's ApplicationMenu with our Applications list
                Director.ScreenManager.Menus.Register(newApp.AppMenu, mnuAppsList);

                // make this the current application
                CurrentApp = newApp;
            }
            catch (Exception ex)
            {
                throw new Exception("App [" + assemblyName + "." + typeName + "] activation: Exception occured (" + ex.Message + ").", ex.InnerException);
            }

        }

        public void Unload(IApplication appToUnload)
        {
            // terminate application
            appToUnload.Deactivate();
            appToUnload.Terminate();

            // clear director reference
            appToUnload.Director = null;

            // unregister the application menu
            Director.ScreenManager.Menus.Unregister(appToUnload.AppMenu);

            // remove the app from loaded apps list
            _Apps.Remove(appToUnload);
        }

        public void UnloadAll()
        {
            foreach (IApplication app in _Apps)
            {
                app.Deactivate();
                app.Terminate();
                app.Director = null;
            }
            _Apps.Clear();
        }

    }
}
